package datatypes;

import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.opengis.feature.simple.SimpleFeature;

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.GeometryFactory;
import java.util.ArrayList;



/**
 * <p>
 * This class represents an Antenna, and all associated parameters for the
 * antenna.  Antenna is backed by the gis feature.
 * </p>
 *  Attributes	<p/>
 *	----------	<p/>
 *	GeometryDescriptorImpl the_geom <Point:Point> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Address <Address:String> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Extra <Extra:String> nillable 0:1	<p/>
 *	AttributeDescriptorImpl City <City:String> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Operator <Operator:String> nillable 0:1	<p/>
 *	AttributeDescriptorImpl File_Name <File_Name:String> nillable 0:1	<p/>
 *	AttributeDescriptorImpl ID <ID:Double> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Status <Status:String> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Ant_Nr <Ant_Nr:String> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Name_Ant <Name_Ant:String> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Azimut <Azimut:Double> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Length <Length:Double> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Width <Width:Double> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Frequency <Frequency:Double> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Heigth <Heigth:Double> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Power <Power:Double> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Tilt <Tilt:Double> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Elec_Tilt <Elec_Tilt:Double> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Mech_Tilt <Mech_Tilt:Double> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Hor_Angle <Hor_Angle:Double> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Vert_Angle <Vert_Angle:Double> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Gain <Gain:Double> nillable 0:1	<p/>
 *	AttributeDescriptorImpl Technology <Technology:String> nillable 0:1	<p/>
 * 
 * @author Bart Moens
 */
public class Antenna {

    private String type;

	private double height_micro;
	private double gain_micro;
	private double power_micro;

	private boolean newnetwork;
	private double height_building;
        
    public Antenna(SimpleFeature antenna) {
        this.antenna = antenna;
    }

    public Antenna(SimpleFeature antenna, Technology technology) {
        this.antenna = antenna;
        ArrayList<Object> tmp = (ArrayList<Object>) antenna.getAttributes();
        String techn = tmp.get(tmp.size()-1).toString();
        if(techn.equals("")) newnetwork = true;
        else newnetwork = false;

        type = "macro";

        if(newnetwork) height_building = getHeight();
        else height_building = 0;

        if(newnetwork) height_micro = height_building;
        else height_micro = technology.getBSHeight("micro");
        gain_micro = technology.getBSAntennaGain_default("micro");
        power_micro = technology.getMaxInputPower("micro");
    }

    public Antenna() {
        // TODO Auto-generated constructor stub
    }

    /**********************************************************************************************/
    /***  ANTENNA ATTRIBUTEN  *********************************************************************/
    /**********************************************************************************************/
    
    /**
     * Heigth
     */
    public double getHeight(){
    	return Double.parseDouble(antenna.getAttribute("Heigth").toString());
    }

	public void setHeight(double i) {
		 antenna.setAttribute("Heigth", (double)i);		
	}
    
    /**
     * Coordinates, buffered
     */
    double x = -1;
    public double getX() {
    	if (x == -1) 
    		x = ((Geometry) antenna.getDefaultGeometry()).getCentroid().getX();
    	return x;
    }
    double y = -1;
    public double getY() {
        if (y == -1) 
        	y = ((Geometry) antenna.getDefaultGeometry()).getCentroid().getY();
        return y;
    }
    public void setX(double x) {
    	this.x = x;
	    GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory( null );
	    Geometry g = geometryFactory.createPoint(new Coordinate(x,y));
	    antenna.setDefaultGeometry(g);    	
    }    
    public void setY(double y) {
    	this.y= y;
	    GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory( null );
	    Geometry g = geometryFactory.createPoint(new Coordinate(x,y));
	    antenna.setDefaultGeometry(g);   
    }
    
    /**
     * Frequency
     */
    public double getFrequency() {
        return Double.parseDouble(antenna.getAttribute("Frequency").toString());
    }

    public void setFrequency(double frequency) {
        antenna.setAttribute("Frequency", frequency);
    }
    
    
    /**
     * POWER
     */
    public double getPower() {
        return Double.parseDouble(antenna.getAttribute("Power").toString());
    }

    public void setPower(double power) {
        antenna.setAttribute("Power", power);
    }
    
    
    /**
     * GAIN
     */
    public double getGain() {
        return Double.parseDouble(antenna.getAttribute("Gain").toString());
    }

    public void setGain(double gain){
    	if(type.equalsIgnoreCase("micro")) gain_micro = gain;
    	else{
    		if(newnetwork) antenna.setAttribute("GAIN", gain);
    		else antenna.setAttribute("Gain", gain);
    	}
    }
    
    /**
     * OPERATOR
     */
    public String getOperator() {
    	return antenna.getAttribute("Operator").toString();
    }


	public void setOperator(String operator) {
		  antenna.setAttribute("Operator", operator);		
	}
    
    /**********************************************************************************************/
    /***  EXTRA ANTENNE PROPERTIES  ***************************************************************/
    /**********************************************************************************************/
    
    /**
     * De backend van de antenna
     */
    protected SimpleFeature antenna;    
    public SimpleFeature getSimpleFeature() {
        return antenna;
    }
    public void setSimpleFeature(SimpleFeature antenna) {
        this.antenna = antenna;
    }
    
    /**
     * If an antenna is an active part of the solution
     */
    protected boolean active;
    public boolean getActive() {
        return active;
    }
    public void setActive(boolean active) {
        this.active = active;
    }
    
    /**
     * AntennaType
     */
    AntennaType antennaType;
    public AntennaType getType() {
        return antennaType;
    }
    public void setType(AntennaType antennaType) {
        this.antennaType = antennaType;
    }
  
    
    /**
     * range
     */
    protected double range;  
    public double getRange() {
        return range;
    }
    public void setRange(double range) {
        this.range = range;
    }
    
    /**
     * Maximum Antenna Power
     */
    double maximumAntennaPower;
	public void setMaximum_output_db(double maximumAntennaPower) {
		this.maximumAntennaPower = maximumAntennaPower;		
	}
	
	/**
	 * If the antenna is the operatorSite, meaning this antenna was not
	 * part of the original antennalist (a default antenna per site)
	 */
	boolean operatorSite = false;
	public void setOperatorSite(boolean b) {
		operatorSite = b;
	}
	public boolean isOperatorSite(){
		return operatorSite;
	}
	
	/**
	 * TerrainType
	 */
    private TerrainType terrainType = null;
	public TerrainType getTerrainType() {
		if (terrainType == null) terrainType = TerrainType.SUBURBAN;
		return terrainType;
	}
	
	public void setTerrainType(TerrainType tp) {
		this.terrainType = tp;
	}
	/**
	 * Returns the euclidian distance between this and another antenna
	 * @param a
	 * @return euclidian distance
	 */
	public double distance(Antenna a) {
		return Math.sqrt(Math.pow(x-a.getX(),2)+Math.pow(y-a.getY(),2));
	}

        public String getCellType(){
    	return type;
    }

    public void setCellType(String ct){
    	if(ct.equalsIgnoreCase("macro") || ct.equalsIgnoreCase("micro")){
    		//if(type.equalsIgnoreCase("macro") && ct.equalsIgnoreCase("micro"))
    			//System.out.println("macro -> micro");
    		//if(type.equalsIgnoreCase("micro") && ct.equalsIgnoreCase("macro"))
    			//System.out.println("micro -> macro");
    		this.type = ct;
    	}
    }
    
    double cost = 0;
    
    public double getCost(){
        return cost;
    }
    public void setCost(double cost){
        this.cost = cost;
    }


	
    /**********************************************************************************************/
    /***  EXTRA JAVA METHODES  ********************************************************************/
    /**********************************************************************************************/
    public Antenna clone() {
        Antenna a = new Antenna();
        
        a.range = range;
        a.antennaType = antennaType;
        a.active = active;
        a.maximumAntennaPower = maximumAntennaPower;
        a.operatorSite = operatorSite;
        a.terrainType = terrainType;
        
        //Feature
        a.antenna = SimpleFeatureBuilder.copy(antenna);
        
        return a;

    }

    @Override 
    public boolean equals(Object a) {
    	if (a instanceof Antenna) {
            if( ((Antenna)a).getX() ==  this.getX() && ((Antenna)a).getY() ==  this.getY() && ((Antenna)a).getHeight() ==  this.getHeight()  &&
                ((Antenna)a).getOperator() ==  this.getOperator()  &&     ((Antenna)a).getFrequency() ==  this.getFrequency()           ) {
        		if (antenna.equals((((Antenna) a).antenna)))
        			return true;
            }
    	}
    	return false;
    }
    
    
    public String toString() {
        return (active ? "[A]" : "[D]") + "Antenna ("+ getOperator() + ") : (" + getX() + "," + getY() + ") @ " + getFrequency() + " Mhz : " + getPower() + "dB" + " T: " + getType().toString();
    }
}